package com.api.apigateway.risk;

/**
 * Isolation Forest 的 ONNX 版打分示意（无外部依赖占位）。
 * 运行逻辑：
 * - 真实项目：使用 onnxruntime.InferenceSession 加载 .onnx 文件；
 * - 这里若线上还未准备模型，采用“统计兜底”：基于 qps、delta、entropy 等做一个简单标准化分。
 */
public class IforestOnnxScorer implements ModelScorer {

    // —— 训练时约定的特征顺序（必须与训练一致）——
    private static final String[] ORDER = new String[]{
        "method_get","method_post","header_cnt","ua_len","query_size","body_size","param_cnt","is_ak_present",
        "has_user","user_mod_10","path_hash_mod_100",
        "qps_user_path","delta_user_path","entropy_ip","ip_hash_mod_1000","ua_hash_mod_1000"
    };

    // 这里演示：无模型文件时的兜底逻辑（归一 + 压缩到 0~1）
    @Override
    public double score(FeatureVector fv) {
        double[] x = fv.toArray(ORDER);

        // 取几项关键特征粗略合成：高 qps、delta 高、熵低 → 异常更高
        double qps = val(fv, "qps_user_path");
        double delta = val(fv, "delta_user_path");
        double H = val(fv, "entropy_ip");

        // 将 qps、delta 用 tanh 压缩到 0~1，熵反向
        double sq = clamp( Math.tanh(qps / 5.0) );           // qps>=5 接近 1
        double sd = clamp( Math.tanh(delta / 3.0) );         // delta>=3 接近 1
        double sh = clamp( 1.0 - Math.tanh(H) );             // 熵越低越危险

        double s = 0.5*sq + 0.3*sd + 0.2*sh;                 // 简单融合
        return clamp(s);
    }

    private static double val(FeatureVector fv, String k){
        Double v = fv.values.get(k);
        return v==null? 0.0 : v.doubleValue();
    }
    private static double clamp(double v){ return Math.max(0.0, Math.min(1.0, v)); }
}